package com.lframework.xingyun.chart.impl;

import com.lframework.common.constants.StringPool;
import com.lframework.common.utils.*;
import com.lframework.starter.redis.components.RedisHandler;
import com.lframework.starter.web.utils.EnumUtil;
import com.lframework.xingyun.chart.dto.OrderChartSameMonthDto;
import com.lframework.xingyun.chart.dto.OrderChartSumDto;
import com.lframework.xingyun.chart.dto.OrderChartTodayDto;
import com.lframework.xingyun.chart.entity.OrderChart;
import com.lframework.xingyun.chart.enums.OrderChartBizType;
import com.lframework.xingyun.chart.mappers.OrderChartMapper;
import com.lframework.xingyun.chart.service.IOrderChartService;
import com.lframework.xingyun.chart.vo.CreateOrderChartVo;
import com.lframework.xingyun.chart.vo.GetOrderChartVo;
import com.lframework.xingyun.chart.vo.QueryOrderChartVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class OrderChartServiceImpl implements IOrderChartService {

    @Autowired
    private OrderChartMapper orderChartMapper;

    @Transactional
    @Override
    public String create(CreateOrderChartVo vo) {

        if (vo.getCreateTime() == null) {
            vo.setCreateTime(LocalDateTime.now());
        }

        OrderChart record = new OrderChart();
        record.setId(IdUtil.getId());
        record.setTotalAmount(vo.getTotalAmount());
        record.setCreateTime(vo.getCreateTime());
        record.setBizType(EnumUtil.getByCode(OrderChartBizType.class, vo.getBizType()));
        record.setCreateDate(DateUtil.formatDate(vo.getCreateTime().toLocalDate()));
        record.setCreateHour(DateUtil.format(vo.getCreateTime(), StringPool.DATE_TIME_HOUR_PATTER));

        orderChartMapper.insert(record);

        return record.getId();
    }

    @Override
    public OrderChartSumDto getTodayChartSum(GetOrderChartVo vo) {

        LocalDate now = LocalDate.now();

        OrderChartSumDto data = orderChartMapper.getChartSum(vo.getBizTypes(), DateUtil.toLocalDateTime(now),
                DateUtil.toLocalDateTimeMax(now));
        if (data == null) {
            data = new OrderChartSumDto();
            data.setTotalAmount(BigDecimal.ZERO);
            data.setTotalNum(0L);
        }

        return data;
    }

    @Override
    public OrderChartSumDto getSameMonthChartSum(GetOrderChartVo vo) {

        LocalDate startDate = LocalDate.now().withDayOfMonth(1);
        LocalDate endDate = startDate.plusMonths(1).minusDays(1);

        OrderChartSumDto data = orderChartMapper.getChartSum(vo.getBizTypes(), DateUtil.toLocalDateTime(startDate), DateUtil.toLocalDateTimeMax(endDate));
        if (data == null) {
            data = new OrderChartSumDto();
            data.setTotalAmount(BigDecimal.ZERO);
            data.setTotalNum(0L);
        }

        return data;
    }

    @Override
    public List<OrderChartTodayDto> queryTodayChart(QueryOrderChartVo vo) {

        LocalDate now = LocalDate.now();

        List<OrderChartTodayDto> results = orderChartMapper
                .queryToday(vo.getBizTypes(), DateUtil.toLocalDateTime(now),
                        DateUtil.toLocalDateTimeMax(now));

        int offset = 24;
        List<OrderChartTodayDto> newResults = new ArrayList<>(offset);

        for (int i = 0; i < offset; i++) {
            LocalTime localTime = LocalTime.of(i, 0, 0);
            String filterDateStr = DateUtil
                    .formatDateTime(LocalDateTime.of(now, localTime), StringPool.DATE_TIME_HOUR_PATTER);
            OrderChartTodayDto result = results.stream().filter(t -> t.getCreateHour().equals(filterDateStr))
                    .findFirst().orElse(null);
            if (result == null) {
                result = new OrderChartTodayDto();
                result.setCreateHour(filterDateStr);
                result.setTotalAmount(BigDecimal.ZERO);
                result.setTotalNum(0);
            }

            newResults.add(result);
        }

        return newResults;
    }

    @Override
    public List<OrderChartSameMonthDto> querySameMonthChart(QueryOrderChartVo vo) {

        LocalDate startDate = LocalDate.now().withDayOfMonth(1);
        LocalDate endDate = startDate.plusMonths(1).minusDays(1);

        List<OrderChartSameMonthDto> results = orderChartMapper
                .querySameMonth(vo.getBizTypes(),
                        DateUtil.toLocalDateTime(startDate), DateUtil.toLocalDateTimeMax(endDate));

        LocalDate lastDate = startDate.plusMonths(1).minusDays(1);
        int offset = lastDate.getDayOfMonth() - startDate.getDayOfMonth() + 1;
        List<OrderChartSameMonthDto> newResults = new ArrayList<>(offset);

        for (int i = 0; i < offset; i++) {
            String filterDateStr = DateUtil.formatDate(startDate.plusDays(i));
            OrderChartSameMonthDto result = results.stream().filter(t -> t.getCreateDate().equals(filterDateStr))
                    .findFirst().orElse(null);
            if (result == null) {
                result = new OrderChartSameMonthDto();
                result.setCreateDate(filterDateStr);
                result.setTotalAmount(BigDecimal.ZERO);
                result.setTotalNum(0);
            }

            newResults.add(result);
        }

        return newResults;
    }
}
